import 'dart:async';

import 'package:adnet_qq/src/splash/platform_interface.dart';
import 'package:adnet_qq/src/splash/splashview_android.dart';
import 'package:adnet_qq/src/splash/splashview_ios.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'constants.dart';
import 'adnet_qq_plugin.dart';


class SplashAdConfig {
  final String posId;

  /// splash container's background image.
  ///
  /// for android, it is the resource identifier(`packageName:resourcesName[-configQualifier]/fileNameWithoutExtension`)
  ///
  /// for iOS, it is the name of an assets
  final String? backgroundImage;

  /// splash container's background color.
  ///
  /// It's an integer representing the color in the default sRGB color space, same as the `Color` in flutter. Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue.
  ///
  ///
  final int? backgroundColor;

  final int? fetchDelay;

  final SplashAdEventCallback adEventCallback;


  SplashAdConfig(this.posId, {required this.adEventCallback, this.backgroundImage, this.backgroundColor, this.fetchDelay});

  toParamMap() {
    return {'posId': posId, 'backgroundImage': backgroundImage, 'backgroundColor': backgroundColor, 'fetchDelay': fetchDelay};
  }

  // Future<void> showAd() async {
  //   await AdnetQqPlugin.channel.invokeMethod('showSplash', {'posId': posId, 'backgroundImage': backgroundImage, 'backgroundColor': backgroundColor, 'fetchDelay': fetchDelay});
  // }
  //
  // Future<void> closeAd() async {
  //   await AdnetQqPlugin.channel.invokeMethod('closeSplash');
  // }
}



/// Optional callback invoked when a web view is first created. [controller] is
/// the [SplashViewController] for the created splash view.
typedef void SplashViewCreatedCallback(SplashViewController controller);

class SplashAdView extends StatefulWidget {
  const SplashAdView({
    Key? key,
    required this.adConfig,
    this.gestureRecognizers,
    this.onSplashViewCreated,
  }) : super(key: key);


  final SplashAdConfig adConfig;


  /// If not null invoked once the splash view is created.
  final SplashViewCreatedCallback? onSplashViewCreated;

  /// Which gestures should be consumed by the splash view.
  ///
  /// It is possible for other gesture recognizers to be competing with the splash view on pointer
  /// events, e.g if the splash view is inside a [ListView] the [ListView] will want to handle
  /// vertical drags. The splash view will claim gestures that are recognized by any of the
  /// recognizers on this list.
  ///
  /// When this set is empty or null, the splash view will only handle pointer events for gestures that
  /// were not claimed by any other gesture recognizer.
  final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

  static SplashViewPlatform? _platform;

  /// Sets a custom [SplashViewPlatform].
  ///
  /// This property can be set to use a custom platform implementation for SplashViews.
  ///
  /// Setting `platform` doesn't affect [SplashAdView]s that were already created.
  ///
  /// The default value is [AndroidSplashView] on Android and [CupertinoSplashView] on iOS.
  static set platform(SplashViewPlatform platform) {
    _platform = platform;
  }

  /// The SplashAdView platform that's used by this SplashAdView.
  ///
  /// The default value is [AndroidSplashView] on Android and [CupertinoSplashView] on iOS.
  static SplashViewPlatform get platform {
    if (_platform == null) {
      switch (defaultTargetPlatform) {
        case TargetPlatform.android:
          _platform = AndroidSplashView();
          break;
        case TargetPlatform.iOS:
          _platform = CupertinoSplashView();
          break;
        default:
          throw UnsupportedError(
              "Trying to use the default SplashAdView implementation for $defaultTargetPlatform but there isn't a default one");
      }
    }
    return _platform!;
  }

  @override
  _SplashViewState createState() => _SplashViewState();

}

class _SplashViewState extends State<SplashAdView> with AutomaticKeepAliveClientMixin {
  final Completer<SplashViewController> _controller = Completer<SplashViewController>();

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return SplashAdView.platform.build(
      context: context,
      creationParams: widget.adConfig.toParamMap(),
      splashViewPlatformCallbacksHandler: widget.adConfig.adEventCallback,
      onSplashViewPlatformCreated: _onWebViewPlatformCreated,
      gestureRecognizers: widget.gestureRecognizers,
    );
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  void didUpdateWidget(SplashAdView oldWidget) {
    super.didUpdateWidget(oldWidget);
    _controller.future.then((SplashViewController controller) {
      controller._updateWidget(widget);
    });
  }

  void _onWebViewPlatformCreated(SplashViewPlatformController splashViewPlatform,) {
    final SplashViewController controller = SplashViewController._(widget, splashViewPlatform);
    _controller.complete(controller);
    if (widget.onSplashViewCreated != null) {
      widget.onSplashViewCreated!(controller);
    }
  }
}

/// Controls a [SplashAdView].
///
/// A [SplashViewController] instance can be obtained by setting the [SplashAdView.onSplashViewCreated]
/// callback for a [SplashAdView] widget.
class SplashViewController {
  SplashViewController._(
      this._widget,
      this._splashViewPlatformController,
      );

  // ignore: unused_field
  final SplashViewPlatformController _splashViewPlatformController;

  // ignore: unused_field
  SplashAdView _widget;

  Future<void> _updateWidget(SplashAdView widget) async {
    _widget = widget;
  }
}

